Skip to content

Add [NonCopyable] for SF002 and make ReadOnlySequenceReadBuffer's sequence parameter scoped - #7

Merged
neuecc merged 2 commits into
mainfrom
noncopyable-attribute
Oct 30, 2026
Merged

neuecc merged 2 commits into
mainfrom
noncopyable-attribute

Conversation

@neuecc

@neuecc neuecc commented Oct 30, 2026

Copy link
Copy Markdown
Member

Two changes requested by the MessagePack for C# v4 work, which is building a reader and a writer that own a SerializerFoundation buffer.

[NonCopyable] for SF002

A serializer's reader or writer is not a buffer, but it holds one by value. Copying it duplicates the inner buffer: two write indexes over one window, and pooled arrays returned twice at Dispose. SF002 could not see this because it only keys on IWriteBuffer / IReadBuffer.

  • Adds SerializerFoundation.CodeAnalysis.NonCopyableAttribute (AttributeTargets.Struct), next to [RequireOverride].
  • SF002 now treats a struct marked with it like a buffer struct. Every existing copy rule applies: by-value and in parameters, assignment, boxing, tuples, foreach, patterns, and so on.
  • The analyzer matches this library's attribute type, not the name, so a same-named attribute from another library is ignored.
  • The attribute is read from the generic definition, so marking Writer<TBuffer> covers every construction.
  • Buffers still need no attribute; implementing the interface remains the marker.
  • The diagnostic message now reads "a buffer, or marked [NonCopyable]". The rule ID, category and severity are unchanged, so the release tracking files don't change.

scoped on the ReadOnlySequenceReadBuffer constructors

Both constructors copy the sequence and never keep a reference to it. Without scoped, though, an in parameter on a ref struct constructor tells the compiler the result may capture that reference. Storing a buffer built from a by-value parameter or a local into a field then failed with CS8347, and callers had to work around it by passing the reference through MemoryMarshal.CreateReadOnlySpan.

  • Both overloads (with and without scratch) now take scoped in ReadOnlySequence<byte>.
  • CompatibleReadOnlySequenceReadBuffer is unchanged. It is not a ref struct, so its in parameter can't be captured.
  • ScopedRefAttribute is emitted for netstandard2.0, netstandard2.1 and net9.0.

Notes for review

  • ReadOnlySequenceReadBufferScopedTest is a compile-time regression check. With scoped removed, the file fails to build with CS8347 (verified locally). It also uses [NonCopyable] through the real analyzer.
  • This adds public API (the attribute), so the next release should probably be a minor version bump.
  • Tests: 150/150 pass locally.

🤖 Generated with Claude Code

neuecc and others added 2 commits October 30, 2026 11:57
A serializer's reader or writer is not a buffer itself but carries one by
value, so copying it duplicates the buffer just as copying the buffer would.
Implementing IWriteBuffer/IReadBuffer stays the implicit marker; structs
marked with SerializerFoundation.CodeAnalysis.NonCopyableAttribute now get
the same SF002 checks. The analyzer keys on this library's attribute type,
not the name, and reads it from the generic definition so every
construction is covered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The constructors copy the sequence and never keep a reference to it, but an
unscoped `in` parameter on a ref struct constructor tells the compiler the
result may capture that reference. Storing a buffer built from a by-value
parameter or a local into a field then failed with CS8347, forcing callers
to launder the reference through MemoryMarshal. The new test holds the buffer
in a field the same way a serializer reader does and fails to compile without
`scoped`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@neuecc
neuecc merged commit fbc1bb4 into main Oct 30, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant